package com.biqee.service.bq.impl;

import java.math.BigDecimal;
import java.util.Date;

import org.apache.log4j.Logger;

import com.biqee.model.db.BqEstimateResult;
import com.biqee.model.db.BqTuan;
import com.biqee.model.db.TbItem;
import com.biqee.model.db.TbShop;
import com.biqee.service.bq.BqEstimateResultService;
import com.biqee.service.bq.EstimateItemService;
import com.biqee.service.tb.TbShopService;
import com.biqee.util.BigDecimalUtil;

public class TaobaoEstimateItemServiceImpl implements EstimateItemService {
	private static final Logger logger = Logger.getLogger(TaobaoEstimateItemServiceImpl.class);
	
	protected static final int ESTIMATE_FAILED = -1;
	
	@Override
	public void estimateItem(TbItem tbItem, TbItem juTbItem, BqTuan bqTuan) {
		if(tbItem == null) {
			logger.error("tbItem is null");
			return;
		}
		
		if(juTbItem == null) {
			logger.error("juTbItem is null");
			return;
		}

		BqEstimateResult bqEstimateResult = bqEstimateResultService.readBySiteItem(bqTuan.getId(), "taobao", tbItem.getTbItemId());
		if(!isNeedEstimate(bqEstimateResult)) {
			return;
		}
		
		String shopId = tbItem.getTbShopId();
		TbShop tbShop = tbShopService.readByTbShopId(shopId);
		if(tbShop == null) {
			logger.error("no tbShop matched for shopId: " + shopId);
			return;
		}
		
		String juShopId = juTbItem.getTbShopId();
		TbShop juTbShop = tbShopService.readByTbShopId(juShopId);
		if(juTbShop == null) {
			logger.error("no juTbShop matched for shopId: " + juShopId);
			return;
		}
		
		int score = estimate(tbItem, tbShop, juTbItem, juTbShop, bqTuan);
		if(score == ESTIMATE_FAILED) {
			logger.error("estimate failed, siteItemId: " + tbItem.getTbItemId());
		}
		
		if(bqEstimateResult == null) {
			bqEstimateResult = new BqEstimateResult();
			bqEstimateResult.setScore(score);
			bqEstimateResult.setSite("taobao");
			bqEstimateResult.setSiteItemId(tbItem.getTbItemId());
			bqEstimateResult.setBqTuanId(bqTuan.getId());
			bqEstimateResultService.create(bqEstimateResult);
		} else {
			bqEstimateResultService.updateScoreById(score, bqEstimateResult.getId());
		}
	}

	private int estimate(TbItem tbItem, TbShop tbShop, TbItem juTbItem, TbShop juTbShop, BqTuan bqTuan) {
		// 注意如果商品为该聚划算活动的商品，我们直接返回 100 分
		// 这里不要对该商品进行解析，因为我们保存到商品价格为实际价格，不是聚划算活动的价格
		// 如果保存聚划算活动的价格，那么这个商品在为别的聚划算活动进行解析时，价格就错了
		if(tbItem.getId().intValue() == juTbItem.getId().intValue()) {
			return 100;
		}
		
		if(tbItem.getTbItemId().equals(juTbItem.getTbItemId())) {
			return 100;
		}
		
		logger.info("estimate target: " + tbItem.getId() + ", referrence: " + juTbItem.getId());
		
		// 价格基数 50，销量基数 20，评价基数 30
		int priceScore = getPriceScore(tbItem, bqTuan);
		int salesScore = getSalesScore(tbItem, juTbItem);
		int gradeScore = getGradeScore(tbShop, juTbShop);
		
		return priceScore + salesScore + gradeScore;
	}
	
	private int getGradeScore(TbShop tbShop, TbShop juTbShop) {
		String tbShopGradeStr = tbShopService.getFinalGrade(tbShop);
		if(tbShopGradeStr == null) {
			logger.error("null shopGradeStr! shopId: " + tbShop.getId());
			return 0;
		}
		
		Double tbShopGrade = Double.valueOf(tbShopGradeStr);
		if(!tbShopService.isMallShop(tbShop)) {
			if(tbShopGrade <= 250.0) {
				tbShopGrade = 2.0;
			} else if(tbShopGrade <= 10000.0) {
				tbShopGrade = 3.0;
			} else if(tbShopGrade <= 500000.0) {
				tbShopGrade = 4.0;
			} else {
				tbShopGrade = 5.0;
			}
		}

		String juShopGradeStr = tbShopService.getFinalGrade(juTbShop);
		if(juShopGradeStr == null) {
			logger.error("null juShopGradeStr! shopId: " + juTbShop.getId());
			return 0;
		}
		
		Double juShopGrade = Double.valueOf(juShopGradeStr);
		if(!tbShopService.isMallShop(juTbShop)) {
			if(juShopGrade <= 250.0) {
				juShopGrade = 2.0;
			} else if(juShopGrade <= 10000.0) {
				juShopGrade = 3.0;
			} else if(juShopGrade <= 500000.0) {
				juShopGrade = 4.0;
			} else {
				juShopGrade = 5.0;
			}
		}
		
		if(tbShopGrade < juShopGrade - 0.5) {
			return 20;
		} else if(tbShopGrade > juShopGrade + 0.5) { 
			return 40;
		} else {
			return 30;
		}
	}
	
	private int getSalesScore(TbItem tbItem, TbItem juTbItem) {
		int base = 20;
		int itemSales = 0;
		int tuanSales = 0;
		try {
			itemSales = tbItem.getSales();
		} catch(Exception ex) {
			// ignore
		}
		try {
			tuanSales = juTbItem.getSales();
		} catch(Exception ex) {
			// ignore
		}

		if(itemSales == 0) {
			if(tuanSales == 0) {
				return base;
			} else {
				return 0;
			}
		}
		
		if(tuanSales == 0) {
			return 2 * base;
		}
		
		int salesDiff = itemSales - tuanSales;
		if(itemSales < tuanSales) {
			salesDiff = -salesDiff;
		}
		
		int diff = 20;
		BigDecimal result = BigDecimalUtil.defaultDivide(new BigDecimal(salesDiff), new BigDecimal(tuanSales));
		if(result.doubleValue() < 0.2) {
			diff = 4;
		} else if(result.doubleValue() < 0.4) {
			diff = 8;
		} else if(result.doubleValue() < 0.6) {
			diff = 12;
		} else if(result.doubleValue() < 0.8) {
			diff = 16;
		} 
		
		if(itemSales > tuanSales) {
			return base + diff;
		} else {
			return base - diff;
		}
	}
	
	private int getPriceScore(TbItem tbItem, BqTuan bqTuan) {
		Double itemPrice = getTbItemPrice(tbItem);
		
		String tuanPriceStr = bqTuan.getTuanPrice();
		Double tuanPrice = Double.valueOf(tuanPriceStr);
		
		Double priceDiff = itemPrice - tuanPrice;
		if(itemPrice < tuanPrice) {
			priceDiff = -priceDiff;
		}
		
		int diff = 50;
		BigDecimal result = BigDecimalUtil.defaultDivide(new BigDecimal(priceDiff), new BigDecimal(tuanPrice));
		if(result.doubleValue() < 0.2) {
			diff = 10;
		} else if(result.doubleValue() < 0.4) {
			diff = 20;
		} else if(result.doubleValue() < 0.6) {
			diff = 30;
		} else if(result.doubleValue() < 0.8) {
			diff = 40;
		} 
		
		int base = 50;
		if(itemPrice < tuanPrice) {
			return base + diff;
		} else {
			return base - diff;
		}
	}
	
	private Double getTbItemPrice(TbItem tbItem) {
		Double minPrice = tbItem.getMinPrice();
		Double maxPrice = tbItem.getMaxPrice();
		Double postFee = tbItem.getPostFee();
		Double price = 0.0;
		if(minPrice == null) {
			price = maxPrice;
		} else if(maxPrice == null) {
			price = minPrice;
		} else {
			price = (minPrice + maxPrice) / 2;
		}
		
		if(postFee == null) {
			return price;
		} else {
			return price + postFee;	
		}
	}
	
	// 一天
	private static final Long RESULT_TIMEOUT_PERIOD = 1 * 24 * 60 * 60 * 1000L;
	private boolean isNeedEstimate(BqEstimateResult result) {
		if(result == null) {
			return true;
		}
		
		Date gmtModified = result.getGmtCreate();
		long lastModifiedTime = gmtModified.getTime();
		long now = new Date().getTime();
		
		return (now - lastModifiedTime) > RESULT_TIMEOUT_PERIOD;
	}
	
	private BqEstimateResultService bqEstimateResultService;

	public void setBqEstimateResultService(
			BqEstimateResultService bqEstimateResultService) {
		this.bqEstimateResultService = bqEstimateResultService;
	}
	
	
	private TbShopService tbShopService;

	public void setTbShopService(TbShopService tbShopService) {
		this.tbShopService = tbShopService;
	}
	
}
